#ifndef USART_H
#define USART_H
/*******************************************************************************
 **  Name: usart.h                                                            **
 **  Description:                                                             **
 **                                                                           **
 **  CDDL: Open Source Initiative (OSI) Approved License                      **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  The contents of this file are subject to the terms of the CDDL:          **
 **  Common Development and Distribution License (the "License").             **
 **  You may not use this file except in compliance with the License.         **
 **                                                                           **
 **  You can obtain a copy of the license at $PROJECT_ROOT/LICENSE            **
 **  or http://www.opensolaris.org/os/licensing.  This code is Open Source    **
 **  and you are free to use it within the confines of the license, even      **
 **  for your own closed-source commercial projects, as long as you follow    **
 **  the terms set forth in the CDDL.                                         **
 **                                                                           **
 **  When distributing Covered Code, include this CDDL HEADER in each         **
 **  file and include the License file at $PROJECT_ROOT/LICENSE.              **
 **  If applicable, add the following below this CDDL HEADER, with the        **
 **  fields enclosed by brackets "[]" replaced with your own identifying      **
 **  information: Portions Copyright [yyyy] [name of copyright owner]         **
 **                                                                           **
 ******************************************************************************/
// $Id: //depot/munix/libmunix/trunk/usart.h#3 $

#include <avr/interrupt.h>
#include <common.h>
#include "rbuff.h"

#if defined(__AVR_ATtiny2313__) || defined(__AVR_ATmega8__) || \
    defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) || \
    defined(__AVR_ATmega8515__)
#define UCSR0B  UCSRB
#define RXCIE0  RXCIE
#define TXCIE0  TXCIE
#define RXEN0   RXEN
#define TXEN0   TXEN
#define UCSR0A  UCSRA
#define UCSR0B  UCSRB
#define UDRE0   UDRE
#define UDR0    UDR
#define U2X0    U2X
#define RXC0    RXC
#define TXC0    TXC
#define UBRR0L  UBRRL
#define UBRR0H  UBRRH
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega328P__)
    // this port nomenclature is the default
    // so we don't have to do anything
#elif defined(__AVR_ATxmega32A4__) || defined(__AVR_ATxmega64A3__) \
    || defined(__AVR_ATxmega128A3__) || defined(__AVR_ATxmega256A3__)

#endif

#define DEFAULT_RXBUFF_SZ	16
#define DEFAULT_TXBUFF_SZ	16

#define USART_TX    0x01
#define USART_RX    0x02


class USART
{
public:
	USART(uint32 b, uint8 d);
	~USART();

    bool        Connect();
    void        SendByte(uint8 a,char c) { tx(c); }
    void        SendWord(uint8,wchar_t);
    
    char        RecvByte() { return rx(); }
    wchar_t     RecvWord();

    uint32      Baud() { return baud; }

    void   EnableInterrupt(uint8 d) {
       if (d == USART_TX) UCSR0B |= (1<<RXCIE0);
       if (d == USART_RX) UCSR0B |= (1<<TXCIE0);
    }
	inline void	tx(char c) {
        while (!(UCSR0A & (1 << UDRE0)));
        UDR0 = c;

    }
	inline char	rx() {
        while (!(UCSR0A & (1 << RXC0)));
        return UDR0;

    }
    void     WriteRAMStr(const char * msg) {
        while (*msg != 0x00) {
            while(!(UCSR0A & (1<<UDRE0)));
            UDR0 = *(msg++);
        }
            //tx(*(msg++));
    }
    void     WriteLine(const char * msg) {
        while (pgm_read_byte(msg) != 0x00) {
            while(!(UCSR0A & (1<<UDRE0)));
            UDR0 = pgm_read_byte(msg++);
        }
            //tx(pgm_read_byte(msg++));
    }

	// Buffer methods
	void	AddToRecv(char c) { rxBuff->Put(c); }
	char	GetFromRecv() { return rxBuff->Get(); }
	char *	GetTXBuff() { return txBuff->Buff(); }
	char *	GetRXBuff() { return rxBuff->Buff(); }
	void	FlushTXBuff() { txBuff->Clear(); }
	void	FlushRXBuff() { rxBuff->Clear(); }

#if defined(USART_OPERATOR_STREAM)
        // Operator overloads for stream buffering-type layout
        USART & operator << (USART &);
        USART & operator << (bool);
        USART & operator << (uint8);    // same as uchar
        USART & operator << (uint16);
        USART & operator << (char);
        USART & operator << (char *);
        USART & operator << (int8_t);
        USART & operator << (int16_t);
#if defined(USART_STREAM_LONG)
        USART & operator << (int32_t);
        USART & operator << (uint32_t);
#endif
#if defined(USART_STREAM_DOUBLE)
        USART & operator << (float);
        USART & operator << (double);
#endif
#endif  /* USART_OPERATOR_STREAM */

private:
    uint32      baud;
    uint16      ubrrval;
    uint8       direction;
    RingBuff *  rxBuff;
    RingBuff *  txBuff;

};
USART & endl(USART &);
// operator overloading with implicit type conversion
USART & operator << (USART &,char);
USART & operator << (USART &,signed char);
USART & operator << (USART &, const unsigned char *);
USART & operator << (USART &, const signed char *);
USART & operator << (USART &, char const * m);


#endif  /* LIBMUNIX_USART_H */
